package hydrap2p.speedlimiter;

import hydrap2p.download.Source;
import hydrap2p.helper.ServiceConnector;
import hydrap2p.helper.ThriftServerThread;
import hydrap2p.helper.ThriftUtils;
import hydrap2p.logging.Level;
import hydrap2p.modulemanager.ModuleControl;
import hydrap2p.servicemanager.NameTaken;

import java.io.IOException;
import java.net.BindException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.thrift.TException;

public class SpeedLimiterServer implements SpeedLimiter.Iface {

	private final SpeedLimiterLogic logic;
	private static ThriftServerThread thread;
	private static ThriftServerThread control;
	
	private static Timer timer;
	private static final long pingerdelay = 10000;
	
	public static void main(String[] args)
	{
		SpeedLimiterServer server=null;
		try {
			server=new SpeedLimiterServer();
			thread=ThriftUtils.initThriftServer(new SpeedLimiter.Processor(server), "SpeedLimiter", 7653);
			control=ThriftUtils.initThriftServer(new ModuleControl.Processor(new SpeedLimiterModuleControl(server)), "SpeedLimiterControl");
		} catch (BindException e) {
			SpeedLimiterLogging.log(Level.FATAL, "Speed Limiter - Startup", "Failed to start listening: "+e.getLocalizedMessage());
		} catch (IOException e) {
			SpeedLimiterLogging.log(Level.FATAL, "Speed Limiter - Startup", "Could not contact Manager");
		} catch (NameTaken e) {
			SpeedLimiterLogging.log(Level.FATAL, "Speed Limiter - Startup", "Another SpeedLimiter is already running");
		}
		if (thread!=null && control!=null)
		{
			thread.start();
			control.start();
		}
		else
			server.shutdown();
		
		SpeedLimiterLogging.log(Level.INFO, "Speed Limiter - Startup", "Successfully started");

	}
	
	public SpeedLimiterServer()
	{
		logic = new SpeedLimiterLogicGlobalTransferQueue();
		timer = new Timer();
		timer.schedule(new PingTimer(), pingerdelay, pingerdelay);
	}
	
	public void shutdown()
	{
		if (thread!=null)
			thread.shutdown();
		if (control!=null)
			control.shutdown();
		if (logic!=null)
			logic.shutdown();
		
		System.exit(0);
	}

	private class PingTimer extends TimerTask {

		@Override
		public void run() {
			try {
				ServiceConnector.getServiceManager().ping();
			} catch (Exception e) {
				SpeedLimiterLogging.log(Level.ERROR, "Speed Limiter - Pinger", "Could not ping Manager, disconnecting");
				shutdown();
			}
		}
	}
	
	
	@Override
	public void attempt(Source arg0, boolean arg1, int arg2) throws TException {
		logic.attempt(arg0, arg1, arg2);
	}

	@Override
	public Map<String, Integer> getQueues() throws TException {
		return logic.getQueues();
	}

	@Override
	public void setQueueLimit(String arg0, int arg1) throws InvalidParameter,
			TException {
		logic.setQueueLimit(arg0, arg1);
	}

	@Override
	public void ping() throws TException {
	}

	@Override
	public List<String> supportedInterfaces() throws TException {
		return Arrays.asList("Service", "SpeedLimiter");
	}
}
